﻿using System;
using System.Data.SqlServerCe;
using System.Diagnostics;
using Outlook = Microsoft.Office.Interop.Outlook;


namespace Investafinance.Sync.Shell
{
    //обалочка для outlook Item со своим New Save Vizit
    internal class Essence<ItemType> where ItemType : class
    {
        //Указатель на обект в Outlook
        public ItemType ItemOtlook;
        // строка конекта к бызе данных
        private string scon;                    // = @"Data Source=C:\Meta.sdf";
        //Название таблиц
        private string nameTable;               // = "Sync_Collaboratori";
        private string nameFolder;              // = "Collaboratore";
        private string typeMessge;              // = "IPM.Contact.Collaboratore";
        ShellFieldItem<ItemType> CollectionField;

        //доступ к полям через 2 string a;
        public string this[string key, string associateKey]
        {
            get 
            { 
                return CollectionField[key, associateKey]; 
            }

            set
            {
                CollectionField[key, associateKey] = value;
            }
        }

        //Конструктор
        public Essence(string nameTableDB, 
                             string nameFolderOutlook, 
                             string connectString, 
                             ItemType ItemFromOutlook, 
                             string MessageClass,
                             ShellFieldItem<ItemType> CollectionFields, string[,] fieldMap)
        {
            this.scon = connectString;
            this.nameTable = nameTableDB;
            this.nameFolder = nameFolderOutlook;
            this.ItemOtlook = ItemFromOutlook;
            this.typeMessge = MessageClass;
            this.CollectionField = CollectionFields;
            CollectionField.UpdateItemOtlook(ItemOtlook);
            associateMap = fieldMap;
        }

        public string[,] associateMap = null;

        //Создать Item в папке Outlook (после необходимо  сохранить)
        public void New(Outlook.MAPIFolder Folder)
        {
            Debug.Assert(Folder != null, "Essence.cs New()  Folder!=null");
            Debug.Assert(typeMessge != null, "Essence.cs New()  typeMessge!=null");

            ItemOtlook = (ItemType)Folder.Items.Add(typeMessge);

            Debug.Assert(ItemOtlook != null, "Essence.cs New()  ItemOtlook!=null");
           
            CollectionField.UpdateItemOtlook(ItemOtlook);

            //добавим поля которые нам нужны UserProperties (если такие есть)
            string[,] data = associateMap;
            if(data != null)
            {
                for (int i = 0; i < Convert.ToInt32(data.Length / 4); i++)
                {
                    if (data[i, 1].IndexOf("UserProperties") != -1)
                    {
                        Outlook.OlUserPropertyType up;

                        switch (data[i, 3])
                        {           
                                case "olOutlookInternal":
                                    up = Outlook.OlUserPropertyType.olCombination;
                                break;
                                case "olCurrency":
                                    up = Outlook.OlUserPropertyType.olCurrency;
                                break;
                                case "olDateTime":
                                    up=Outlook.OlUserPropertyType.olDateTime;
                                break;
                                case "olDuration":
                                    up=Outlook.OlUserPropertyType.olDuration;
                                break;
                                case "olEnumeration":
                                    up=Outlook.OlUserPropertyType.olEnumeration;
                                break;
                                case "olFormula":
                                    up=Outlook.OlUserPropertyType.olFormula;
                                break;
                                case "olInteger":
                                    up=Outlook.OlUserPropertyType.olInteger;
                                break;
                                case "olNumber":
                                    up = Outlook.OlUserPropertyType.olNumber;
                                break;
                                case "olPercent":
                                    up = Outlook.OlUserPropertyType.olPercent;
                                break;
                                case "olSmartFrom":
                                    up = Outlook.OlUserPropertyType.olSmartFrom;
                                break;
                                case "olText":
                                    up = Outlook.OlUserPropertyType.olText;
                                break;
                                case "olYesNo":
                                    up = Outlook.OlUserPropertyType.olYesNo;
                                break;
                                default:
                                    up = Outlook.OlUserPropertyType.olText;
                                break;
                        }

                        //получим имя или число
                        string s = data[i, 1].Replace("UserProperties", "").Replace("[", "").Replace("]", "");


                        if (ItemOtlook is Outlook.TaskItem)
                        {
                            try
                            {
                                //попробуем преобразовать в число
                                Convert.ToInt32(s);
                                //если число тогда назавём своёство также как и колонку
                                ((Outlook.TaskItem)ItemOtlook).UserProperties.Add(data[i, 2], up, null, 3);
                            }
                            catch
                            {
                                //если exeption то это имя UserProperties
                                ((Outlook.TaskItem)ItemOtlook).UserProperties.Add(s, up, null, 3);
                            }
                            
                        }
                        else
                            if (ItemOtlook is Outlook.ContactItem)
                            {
                                try
                                {
                                    //попробуем преобразовать в число
                                    Convert.ToInt32(s);
                                    //если число тогда назавём свойство также как и колонку
                                    ((Outlook.ContactItem)ItemOtlook).UserProperties.Add(data[i, 2], up, null, 3);
                                }
                                catch
                                {
                                    //если exeption то это имя UserProperties
                                    ((Outlook.ContactItem)ItemOtlook).UserProperties.Add(s, up, null, 3);
                                }
                            }
                            else
                                if (ItemOtlook is Outlook.PostItem)
                                {
                                    try
                                    {
                                        //попробуем преобразовать в число
                                        Convert.ToInt32(s);
                                        //если число тогда назавём свойство также как и колонку
                                        ((Outlook.PostItem)ItemOtlook).UserProperties.Add(data[i, 2], up, null, 3);
                                    }
                                    catch
                                    {
                                        //если exeption то это имя UserProperties
                                        ((Outlook.PostItem)ItemOtlook).UserProperties.Add(s, up, null, 3);
                                    }
                                    
                                }
                                else
                                    if (ItemOtlook is Outlook.MailItem)
                                    {
                                        try
                                        {
                                            //попробуем преобразовать в число
                                            Convert.ToInt32(s);
                                            //если число тогда назавём свойство также как и колонку
                                            ((Outlook.MailItem)ItemOtlook).UserProperties.Add(data[i, 2], up, null, 3);
                                        }
                                        catch
                                        {
                                            //если exeption то это имя UserProperties
                                            ((Outlook.MailItem)ItemOtlook).UserProperties.Add(s, up, null, 3);
                                        }
                                    }
                    }
                }
            }          
        }

        //Сохранение (запись в базу добавление в таблицу папки записи...)
        public bool Save()
        {
            Debug.Assert(ItemOtlook != null, "Essence.cs Save()  ItemOtlook!=null");

            if (ItemOtlook != null)
            {
                bool ret = true;
                SqlCeConnection conn = new SqlCeConnection(scon);
                try
                {
                    //открываем подключение к бызе
                    conn.Open();
                    //Нужно сохранить чтобы назначить EntryID
                    string EntryID = "";
                    if (ItemOtlook is Outlook.TaskItem)
                    { 
                        ((Outlook.TaskItem)ItemOtlook).Save();
                        EntryID = ((Outlook.TaskItem)ItemOtlook).EntryID;
                    }
                        else
                    if (ItemOtlook is Outlook.ContactItem)
                    { 
                        ((Outlook.ContactItem)ItemOtlook).Save();
                        EntryID = ((Outlook.ContactItem)ItemOtlook).EntryID;
                    }
                        else
                    if (ItemOtlook is Outlook.NoteItem)
                    {
                        ((Outlook.NoteItem)ItemOtlook).Save();
                        EntryID = ((Outlook.NoteItem)ItemOtlook).EntryID;
                    }
                        else
                    if (ItemOtlook is Outlook.PostItem)
                    {
                        ((Outlook.PostItem)ItemOtlook).Save();
                        EntryID = ((Outlook.PostItem)ItemOtlook).EntryID;
                    }   
                            //ItemOtlook.Save();
                    string sName = "(";
                    string sValue = "(";
                    for (int i = 0; i < CollectionField.GetCountField(); i++)
                    {
                        sName += CollectionField.GetNameField(i) + ",";
                        sValue += "'" + CollectionField.GetValueField(i) + "',";
                    }
                    sName += "Modify,EntryIDInOutlook)";
                    sValue += "'','" + EntryID + "')";

                    SqlCeCommand cmd;
                    //Создаём новую запись в бд
                    cmd = new SqlCeCommand("INSERT INTO Sync_" + nameTable + " " + sName + "VALUES " + sValue + ";", conn);
                    //выполняем команду этот оператор значит выполнить отличную от Select
                    cmd.ExecuteNonQuery();
                    cmd.Dispose();
                    cmd = null;

                    //Сохраним в самом Outlook е
                    if (ItemOtlook is Outlook.TaskItem)
                    {
                        ((Outlook.TaskItem)ItemOtlook).Save();
                    }
                        else
                    if (ItemOtlook is Outlook.ContactItem)
                    {
                        ((Outlook.ContactItem)ItemOtlook).Save();
                    }
                        else
                    if (ItemOtlook is Outlook.NoteItem)
                    {
                        ((Outlook.NoteItem)ItemOtlook).Save();
                    }
                        else
                    if (ItemOtlook is Outlook.PostItem)
                    {
                        ((Outlook.PostItem)ItemOtlook).Save();                                    
                    }   
                }
                catch (Exception err)
                {
                    ret = false;
                    Debug.Assert(false, "Essence.cs Save()" + "\n" + err.Message + "\n -->" + err.Source + "\n");
                }
                finally
                {
                    //закрываем подключение к базе 
                    conn.Close();
                    conn.Dispose();
                    conn = null;
                }
                return ret;
            }
            else
            return false;
        }

        //показать Vizit (вызывать после загрузки)
        public void Viev()
        {
            Debug.Assert(ItemOtlook != null, "Essence.cs Viev()  ItemOtlook != null");

            if (ItemOtlook != null)
            {
                if (ItemOtlook is Outlook.TaskItem)
                {
                    ((Outlook.TaskItem)ItemOtlook).Display(false);
                }
                    else
                if (ItemOtlook is Outlook.ContactItem)
                {
                    ((Outlook.ContactItem)ItemOtlook).Display(false);
                }
                    else
                if (ItemOtlook is Outlook.NoteItem)
                {
                    ((Outlook.NoteItem)ItemOtlook).Display(false);
                }
                    else
                if (ItemOtlook is Outlook.PostItem)
                {
                    ((Outlook.PostItem)ItemOtlook).Display(false);                                   
                }   
            }
        }

        //удалить Vizit (вызывать после загрузки)
        public void RemuveInOutlook()
        {
            Debug.Assert(ItemOtlook != null, "Essence.cs RemuveInOutlook()  ItemOtlook != null");

            if (ItemOtlook != null)
            {
                if (ItemOtlook is Outlook.TaskItem)
                {
                    ((Outlook.TaskItem)ItemOtlook).Delete();
                }
                    else
                if (ItemOtlook is Outlook.ContactItem)
                {
                    ((Outlook.ContactItem)ItemOtlook).Delete();
                }
                    else
                if (ItemOtlook is Outlook.NoteItem)
                {
                    ((Outlook.NoteItem)ItemOtlook).Delete();
                }
                    else
                if (ItemOtlook is Outlook.PostItem)
                {
                    ((Outlook.PostItem)ItemOtlook).Delete();         
                }   
            }
        }

        //сначало обновить поля в оутлуке потом Сохранение Vizit стандартное оутлукавское
        public void Update()
        {
            Debug.Assert(ItemOtlook != null, "Essence.cs Update()  ItemOtlook != null");

            if (ItemOtlook != null)
            {
                if (ItemOtlook is Outlook.TaskItem)
                {
                    ((Outlook.TaskItem)ItemOtlook).Assign();
                    ((Outlook.TaskItem)ItemOtlook).Save();
                }
                    else
                if (ItemOtlook is Outlook.ContactItem)
                {
                    ((Outlook.ContactItem)ItemOtlook).Save();
                }
                    else
                if (ItemOtlook is Outlook.NoteItem)
                {
                    ((Outlook.NoteItem)ItemOtlook).Save();
                }
                    else
                if (ItemOtlook is Outlook.PostItem)
                {
                    ((Outlook.PostItem)ItemOtlook).Save();         
                }   
            }
        }

        //Сохранение стандартное оутлукавское
        public void SaveInOutlook()
        {
            Debug.Assert(ItemOtlook != null, "Essence.cs SaveInOutlook()  ItemOtlook != null");

            if (ItemOtlook != null)
            {
                if (ItemOtlook is Outlook.TaskItem)
                {
                    ((Outlook.TaskItem)ItemOtlook).Save();
                }
                    else
                if (ItemOtlook is Outlook.ContactItem)
                {
                    ((Outlook.ContactItem)ItemOtlook).Save();
                }
                    else
                if (ItemOtlook is Outlook.NoteItem)
                {
                    ((Outlook.NoteItem)ItemOtlook).Save();
                }
                    else
                if (ItemOtlook is Outlook.PostItem)
                {
                    ((Outlook.PostItem)ItemOtlook).Save();         
                }   
            }
        }

        //Закрыть Vizit стандартное оутлукавское без сохранения
        public void CloseNONSaveInOutlook()
        {
            Debug.Assert(ItemOtlook != null, "Essence.cs CloseNONSaveInOutlook()  ItemOtlook != null");

            if (ItemOtlook != null)
            {
                if (ItemOtlook is Outlook.TaskItem)
                {
                    ((Outlook._TaskItem)ItemOtlook).Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard);
                }
                    else
                if (ItemOtlook is Outlook.ContactItem)
                {
                    ((Outlook._ContactItem)ItemOtlook).Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard);
                }
                    else
                if (ItemOtlook is Outlook.NoteItem)
                {
                    ((Outlook.NoteItem)ItemOtlook).Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard);
                }
                    else
                if (ItemOtlook is Outlook.PostItem)
                {
                    ((Outlook._PostItem)ItemOtlook).Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard);         
                }   
            }
        }

        //НАйти в Оутлук Item и загрузить в обьект 
        public bool Load(string EntryID)
        {
            Debug.Assert(EntryID != null, "Essence.cs Load()  EntryID != null");
            Debug.Assert(EntryID != "", "Essence.cs Load()  EntryID != ''");

            bool ret = true;
            SqlCeConnection conn = new SqlCeConnection(scon);
            try
            {
                //открываем подключение к бызе
                conn.Open();
                conn.InitializeLifetimeService();
                SqlCeCommand cmd = new SqlCeCommand("select EntryIDInOutlook from Sync_" + nameTable + " where ID in ('" + EntryID + "');", conn);
                //выполняем селект
                SqlCeDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow);
                if (dr.Read())
                {
                    string EntryItem = dr["EntryIDInOutlook"].ToString();
                    dr.Close();
                    cmd = new SqlCeCommand("select StoreID from Folders where Name='" + nameFolder + "'; ", conn);
                    //выполняем селект
                    dr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow);
                    if (dr.Read())
                    {
                        string StoreIDInFolder = dr["StoreID"].ToString();
                        ItemOtlook = ((ItemType)ShellFolderSync<ItemType>.localApplication.Session.GetItemFromID(EntryItem, StoreIDInFolder));
                        CollectionField.UpdateItemOtlook(ItemOtlook);
                        dr.Close();
                        cmd = new SqlCeCommand("select * from Sync_" + nameTable + " where ID in ('" + EntryID + "');", conn);
                        //выполняем селект
                        dr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow);
                        if (dr.Read())
                        {
                            for (int i = 0; i < CollectionField.GetCountField(); i++)
                            { 
                                string sName=CollectionField.GetNameField(i);
                                this.CollectionField[sName, ""] = dr[sName].ToString();
                            }
                        }
                        dr.Close();
                    }
                }
            }
            catch (Exception err)
            {
                ret = false;
                Debug.Assert(false, "Essence.cs Load()" + "\n" + err.Message + "\n -->" + err.Source + "\n");
            }
            finally
            {
                //закрываем подключение к базе 
                conn.Close();
                conn.Dispose();
                conn = null;
            }
            return ret;
        }

        //Загрузить Item которого нет в оутлук но есть в БД
        public bool LoadItemNonOutlook(Outlook.MAPIFolder Folder, string EntryID)
        {
            Debug.Assert(Folder != null, "Essence.cs LoadItemNonOutlook()  EntryID != Folder");
            Debug.Assert(EntryID != null, "Essence.cs LoadItemNonOutlook()  EntryID != null");
            Debug.Assert(EntryID != "", "Essence.cs LoadItemNonOutlook()  EntryID != ''");

            //Создаём 
            this.New(Folder);

            bool ret = true;
            SqlCeConnection conn = new SqlCeConnection(scon);
            try
            {
                //открываем подключение к бызе
                conn.Open();
                SqlCeCommand cmd = new SqlCeCommand("select * from Sync_" + nameTable + " where ID in ('" + EntryID + "');", conn);
                //выполняем селект
                SqlCeDataReader dr = cmd.ExecuteReader();
                cmd.Dispose();
                cmd = null;
                if (dr.Read())
                {
                    for (int i = 0; i < CollectionField.GetCountField(); i++)
                    {
                        string sName = CollectionField.GetNameField(i);
                        switch (sName)
                        {
                            case "ID":
                                CollectionField[sName, "Mileage"] = dr[sName].ToString().Trim();
                                break;
                            case "WorkCity":
                                CollectionField[sName, "BusinessAddressCity"] = dr[sName].ToString().Trim();
                                break;
                            case "UserField1":
                                CollectionField[sName, "User1"] = dr[sName].ToString().Trim();
                                break;
                            case "UserField2":
                                CollectionField[sName, "User2"] = dr[sName].ToString().Trim();
                                break;
                            case "UserField3":
                                CollectionField[sName, "User3"] = dr[sName].ToString().Trim();
                                break;
                            case "UserField4":
                                CollectionField[sName, "User4"] = dr[sName].ToString().Trim();
                                break;
                            case "Email":
                                CollectionField[sName, "Email1Address"] = dr[sName].ToString().Trim();
                                break;
                            case "Email2":
                                CollectionField[sName, "Email2Address"] = dr[sName].ToString().Trim();
                                break;
                            case "Email3":
                                CollectionField[sName, "Email3Address"] = dr[sName].ToString().Trim();
                                break;
                            default:
                                CollectionField[sName, sName] = dr[sName].ToString().Trim();
                                break;
                        }
                    }
                }
                dr.Close();
            }
            catch (Exception err)
            {
                ret = false;
                Debug.Assert(false, "Essence.cs LoadItemNonOutlook()" + "\n" + err.Message + "\n -->" + err.Source + "\n"); 
            }
            finally
            {
                //закрываем подключение к базе 
                conn.Close();
                conn.Dispose();
                conn = null;
            }
            return ret;
        }
    }
}
